﻿package Gameplay.Visualizer
{

    import flash.geom.ColorTransform;
    import flash.geom.Point;    
    import flash.media.SoundChannel;    
    import flash.media.SoundMixer; 
	import flash.filters.BlurFilter;
    import flash.utils.ByteArray;
    import flash.events.Event;
    import flash.display.Sprite;
    import flash.display.BitmapData;
    import flash.display.Bitmap;
    import flash.display.Shape;
	
	public class PlasmaVisualizer extends AbstractVisualizer
	{
		private const CRadius:uint = 100;                      
        private var FCircle:PlasmaCircle;
        private var FCount:uint = 0;		
		private var FWidth:Number;
		private var FHeight:Number;
		private var FCanvas:BitmapData;
		private var FBitmap:Bitmap;
		private var FDrawer:Shape;
		private var FColorTransform:ColorTransform;
		
		public function PlasmaVisualizer():void
		{			
			FCircle = new PlasmaCircle(0, 128);
			FCount = 0;
			
			FWidth = new Number(390);
			FHeight = new Number(390);
			FCanvas = new BitmapData(FWidth, FHeight, true, 0xFFFFFFFF);
			FBitmap = new Bitmap(FCanvas);
			FDrawer = new Shape();
			FDrawer.graphics.beginFill(0x000000, 1);
			FDrawer.graphics.drawRect(0, 0, FWidth, FHeight);
			FDrawer.graphics.endFill();
			FColorTransform = new ColorTransform();
			addChild(FBitmap);		
		}
		
		override protected function OnEnterFrame(e:Event):void
		{
            if (FChannel) 
			{
                UpdateCircle();
            }            
			
			var vVertex:Vertex;
			var i:int;
			FDrawer.graphics.clear();
			FDrawer.graphics.beginFill(0x000000, 0);
			FDrawer.graphics.lineStyle(1, 0xFFFFFF);
			FDrawer.graphics.moveTo(FCircle.Vertices[0].x/2 + FWidth / 2, FCircle.Vertices[0].y/2 + FHeight / 2);
			
			for (i = 0; i < FCircle.Vertices.length; i++) 							
			{
				vVertex = FCircle.Vertices[i];
            	FDrawer.graphics.lineTo(vVertex.x/2 + FWidth / 2, vVertex.y/2 + FHeight / 2);
				FDrawer.graphics.moveTo(vVertex.x/2 + FWidth / 2, vVertex.y/2 + FHeight / 2);
			}			
			
			for (i = 0; i < 3; i++)
			{
				vVertex = FCircle.Vertices[i];
            	FDrawer.graphics.lineTo(vVertex.x/2 + FWidth / 2, vVertex.y/2 + FHeight / 2);
				FDrawer.graphics.moveTo(vVertex.x/2 + FWidth / 2, vVertex.y/2 + FHeight / 2);
			}				
			FDrawer.graphics.endFill();
			FCanvas.draw(FDrawer);
			var vAmplitude:Number = Math.max(FChannel.rightPeak, FChannel.leftPeak) * 0.02;
            FColorTransform.redMultiplier += (0.5 - Math.random()) * vAmplitude;
            FColorTransform.blueMultiplier += (0.5 - Math.random()) * vAmplitude;
            FColorTransform.greenMultiplier += (0.5 - Math.random()) * vAmplitude;
            FColorTransform.redMultiplier = Math.min(Math.max(FColorTransform.redMultiplier, 0.85), 1);
            FColorTransform.blueMultiplier = Math.min(Math.max(FColorTransform.blueMultiplier, 0.8), 1);
            FColorTransform.greenMultiplier = Math.min(Math.max(FColorTransform.greenMultiplier, 0.8), 1);
			
            if (FCount++ % 3 == 0) 
			{
                FCanvas.colorTransform(FCanvas.rect, FColorTransform);
            }
            if (FCount % 5 == 0) 
			{
                FCanvas.applyFilter(FCanvas, FCanvas.rect, new Point(0, 0), new BlurFilter(4, 4));
            }        
		}
		
		private function UpdateCircle():void
		{
            var vData:ByteArray = new ByteArray();
            SoundMixer.computeSpectrum(vData, true);            
            var vVolume:Vector.<Number> = new Vector.<Number>(128);
            for (var i:uint = 0; i < 64; i++) 
			{
                vVolume[i] = 128 * Math.sqrt((vData.readFloat() + vData.readFloat() + vData.readFloat() + vData.readFloat()) / 4);
            }
            for (var j:uint = 0; j < 64; j++)
			{
                vVolume[128 - j - 1] = 128 * Math.sqrt((vData.readFloat() + vData.readFloat() + vData.readFloat() + vData.readFloat()) / 4);
            }
            FCircle.Radius = CRadius * (FChannel.leftPeak + FChannel.rightPeak);
            FCircle.Update(vVolume);
        }
	}	
}

